package com.lcy.controller;

import com.mybatisflex.core.paginate.Page;
import com.lcy.codesandbox.model.JudgeInfo;
import com.lcy.execudeCode.JudgeService;
import com.lcy.manager.AiManager;
import com.lcy.mapstruct.ProblemSubmitConverter;
import com.lcy.model.common.Paging;
import com.lcy.model.dto.problemSubmit.OjProblemSubmitQueryRequest;
import com.lcy.model.dto.problemSubmit.OjProblemSubmitVo;
import com.lcy.model.dto.problemSubmit.ProblemSubmitAddRequest;
import com.lcy.model.entity.AiCodeAnalysis;
import com.lcy.reuslt.Result;
import com.lcy.security.utils.SecurityHelper;
import com.lcy.service.AiCodeAnalysisService;
import com.lcy.service.OjProblemSubmitService;
import com.lcy.sys.model.entity.SysUser;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

@Slf4j  // 添加在类上
@RequiredArgsConstructor // Lombok 自动注入
@RestController
@Tag(name = "OjProblemSubmit", description = "题目提交管理")
@RequestMapping("/submit")
public class OjProblemSubmitController {

	@Resource
	private OjProblemSubmitService ojProblemSubmitService;
	@Resource
	private AiManager aiManager;

	@Resource
	private AiCodeAnalysisService aiCodeAnalysisService;

	@Resource
	private JudgeService judgeService;

	@Resource
	private ProblemSubmitConverter problemSubmitConverter;
	//region AI生成分析报告功能
	private static final String AI_ANALYSIS_SYSTEM_MESSAGE = "你是一位专业的编程导师，我会给你如下信息：\n" +
			"、、、\n" +
			"题目名称，\n" +
			"判题信息，\n" +
			"用户代码\n" +
			"、、、\n" +
			"1.请你根据上述提供的信息，按照以下要求对用户提供的代码进行详细分析\n" +
			"2.请严格按照以下 JSON 数组输出分析结果，不要额外出现JSON数组以外的解释信息，JSON数组中各参数对应的返回建议内容要尽量的详细、专业：\n" +
			"```\n" +
			"{\n" +
			"  \"syntaxCheck\": {(要求：如果没有错误，返回空数组。)\n" +
			"    \"hasError\": true/false,\n" +
			"    \"errors\": [\n" +
			"      {\n" +
			"        \"line\": 如果有错误，明确指出错误的位置（行号）,\n" +
			"        \"type\": \"错误类型\",\n" +
			"        \"message\": \"如果有错误，明确指出错误描述\",\n" +
			"        \"suggestion\": \"如有错误请指出明确的详细的修复建议\"\n" +
			"      }\n" +
			"    ]\n" +
			"  },\n" +
			"  \"logicErrors\": [\n"+
			"    {\n" +
			"      \"description\": \"逻辑错误描述,分析代码逻辑是否正确,是否存在潜在的错误（如空指针异常、数组越界、类型不匹配等）\",\n" +
			"      \"cause\": \"对每个逻辑错误，提供详细的描述、可能的原因和可能的原因\",\n" +
			"      \"suggestion\": \"对每个逻辑错误，提供详细的改进建议\"\n" +
			"    }\n" +
			"  ],\n" +
			"  \"optimizationSuggestions\": [\n" +
			"    {\n" +
			"      \"area\": \"优化领域（如算法、代码结构）\",\n" +
			"      \"suggestion\": \"具体优化建议：从代码结构、算法效率、可读性、可维护性等方面提出优化建议,每个建议应具体且可操作，例如：'使用 HashMap 优化查找效率' 或 '将重复代码提取为方法'。\"\n" +
			"    }\n" +
			"  ],\n" +
			"  \"codeAnalysis\": {\n" +
			"    \"complexity\": {\n" +
			"      \"time\": \"分析代码的时间复杂度\",\n" +
			"      \"space\": \"分析代码的空间复杂度\"\n" +
			"    },\n" +
			"    \"style\": {\n" +
			"      \"naming\": \"分析代码风格-命名规范评价\",\n" +
			"      \"comments\": \"分析代码风格-注释完整性评价\",\n" +
			"      \"formatting\": \"分析代码风格-代码格式评价\"\n" +
			"    },\n" +
			"    \"paradigm\": \"分析代码中使用的编程范式（如面向对象、函数式编程）。\"\n" +
			"  },\n" +
			"  \"learningPath\": [ \n" +
			"    {\n" +
            "      \"learningSuggestion\": \"根据代码特征和用户可能的知识盲区，生成深入详细的学习建议，学习建议应结合代码特征和用户可能的知识盲区，提供具体且可操作的建议。\",\n" +
			"      \"topic\": \"学习主题\",\n" +
			"      \"resources\": [\"具体的学习资源（如书籍、课程、文档链接）-学习资源1\", \"具体的学习资源（如书籍、课程、文档链接）-学习资源2\"],\n" +
			"      \"exercises\": [\"具体的练习方向（如算法练习、设计模式实践）-练习方向1\", \"具体的练习方向（如算法练习、设计模式实践）-练习方向2\"]\n" +
			"    }\n" +
			"  ]\n" +
			"}\n" +
//            "2.
//            "3. logicErrors参数对应的是逻辑错误识别，其对应的JSON格式的内容要求如下：\n" +
//            "   +
//            "4. optimizationSuggestions参数对应的是代码优化建议，其对应的JSON格式的内容要求如下：\n" +
//            "   - 从代码结构、算法效率、可读性、可维护性等方面提出优化建议。\n" +
////            "   - 每个建议应具体且可操作，例如：'使用 HashMap 优化查找效率' 或 '将重复代码提取为方法'。\n" +
//            "5. codeAnalysis参数对应的是代码特征分析，其对应的JSON格式的内容要求如下：\n" +
//            "   - 分析代码的复杂度（如时间复杂度、空间复杂度）。\n" +
//            "   - 分析代码风格（如命名规范、注释完整性、代码格式）。\n" +
//            "   - 分析代码中使用的编程范式（如面向对象、函数式编程）。\n" +
//            "6. learningPath参数对应的是个性化学习路线建议，其对应的JSON格式的内容要求如下：**：\n" +
//            "   - 根据代码特征和用户可能的知识盲区，生成深入详细的学习建议。\n" +
//            "   - 学习建议应包括具体的学习资源（如书籍、课程、文档链接）和练习方向（如算法练习、设计模式实践）。\n" +
            "\n" +
			"注意：\n" +
			"1. 所有字段必须严格按照格式返回，字段对应的内容要详细详细再详细，尽可能的专业周全，把额外的解释都放到字段对应的内容中去，即使没有错误或建议，也应返回空数组或默认值。\n" +
			"2. 学习资源应尽量提供权威、免费的资源链接（如官方文档、开源课程）。"+
	        "3.内容中不要出现：（注释完整性评价：代码中缺乏注释，建议添加必要的说明以提高可读性。）这种，只需要说后面的内容不需要重复一遍标题，也就是只需要说代码中缺乏注释，建议添加必要的说明以提高可读性。 而不要加前面的注释完整性评价：";

	//用户提供信息生成
//	private String getGenerateUserMessage(OjProblemSubmitVo problemSubmitVo) {
//		StringBuilder userMessage = new StringBuilder();
//		userMessage.append("题目名称：").append(problemSubmitVo.getTitle()).append("\n");
//		userMessage.append("判题信息：").append(problemSubmitVo.getJudgeInfo()).append("\n");
//		userMessage.append("用户代码：").append(problemSubmitVo.getCode()).append("\n");
//		return userMessage.toString();
//	}
	// 替换原有的 getGenerateUserMessage 方法
	private String getGenerateUserMessage(OjProblemSubmitVo problemSubmitVo) {
		StringBuilder userMessage = new StringBuilder();

		// 1. 题目名称
		userMessage.append("题目名称：")
				.append(problemSubmitVo.getTitle() != null ? problemSubmitVo.getTitle() : "未知题目")
				.append("\n\n");

		// 2. 用户代码
		userMessage.append("代码语言及用户代码：\n```")
				.append(problemSubmitVo.getLanguage() != null ? problemSubmitVo.getLanguage() : "")
				.append("\n")
				.append(problemSubmitVo.getCode() != null ? problemSubmitVo.getCode() : "")
				.append("\n```\n\n");

		//3.判题配置
		userMessage.append("具体的题目要求：\n")
				.append(problemSubmitVo.getJudgeConfig() != null ? problemSubmitVo.getJudgeConfig() : "")
				.append("\n");

		// 3. 判题信息（增加null检查）
		JudgeInfo judgeInfo = problemSubmitVo.getJudgeInfo();
		userMessage.append("判题结果：\n");
		if (judgeInfo != null) {
			userMessage.append("- 状态：")
					.append(judgeInfo.getMessage() != null ? judgeInfo.getMessage() : "无状态信息")
					.append("\n")
					.append("- 耗时：")
					.append(judgeInfo.getTime() != null ? judgeInfo.getTime() + "ms" : "无耗时数据")
					.append("\n")
					.append("- 内存：")
					.append(judgeInfo.getMemory() != null ? judgeInfo.getMemory() + "KB" : "无内存数据")
					.append("\n");
		} else {
			userMessage.append("- 无判题信息\n");
		}

		// 4. 输出结果
		if (problemSubmitVo.getOutput() != null && !problemSubmitVo.getOutput().isEmpty()) {
			userMessage.append("实际输出：\n")
					.append(String.join("\n", problemSubmitVo.getOutput()))
					.append("\n");
		}

		return userMessage.toString();
	}

	//endregion

	//	@PostMapping("/aiAnalysis/{id}")
//	@Operation(summary = "AI分析")
//	public Result<String> aiAnalysis(@PathVariable Long id) {
//		OjProblemSubmitVo problemSubmitVo = ojProblemSubmitService.getInfoById(id);
//		String userMessage = getGenerateUserMessage(problemSubmitVo);
//		String systemMessage =
//	}
	@PostMapping("/")
	@Operation(summary = "提交题目")
	public Result<Long> doQuestionSubmit(@Valid @RequestBody ProblemSubmitAddRequest problemSubmitAddRequest)
			throws Exception {
		try {
			SysUser user = SecurityHelper.getUser();
			Long problemSubmitId = ojProblemSubmitService.doSubmit(problemSubmitAddRequest, user);
			OjProblemSubmitVo ojProblemSubmitVo = ojProblemSubmitService.getInfoById(problemSubmitId);
			//封装prompt
//			String userMessage = getGenerateUserMessage(ojProblemSubmitVo);
			//异步调用AI生成
//		CompletableFuture<String> future = aiManager.doAsyncStableRequest(AI_ANALYSIS_SYSTEM_MESSAGE, userMessage);
//		future.thenAccept(result -> {
//			AiCodeAnalysis analysis = new AiCodeAnalysis();
//			analysis.setProblemSubmitId(problemSubmitId);
//			analysis.setAnalysisResult(result);
//			aiCodeAnalysisService.saveAnalysis(analysis);
//		});
			// 增强异步处理
//		CompletableFuture<String> future = aiManager.doAsyncStableRequest(AI_ANALYSIS_SYSTEM_MESSAGE, userMessage);
//		future.handle((result, ex) -> {
//			if (ex != null) {
//				log.error("AI分析失败", ex);
//				// 可以记录失败状态，但不影响主流程
//				return null;
//			}
//			AiCodeAnalysis analysis = new AiCodeAnalysis();
//			analysis.setProblemSubmitId(problemSubmitId);
//			analysis.setAnalysisResult(result);
//			aiCodeAnalysisService.saveAnalysis(analysis);
//			return result;
//		});
//
//		return Result.success(problemSubmitId);
//	} catch (Exception e) {
//		log.error("提交失败", e);
//			return null;
//	}
			// 增强异步处理
//			CompletableFuture.runAsync(() -> {
//				try {
//					log.info("开始AI分析处理，提交ID: {}", problemSubmitId);
//					String result = aiManager.doSyncStableRequest(AI_ANALYSIS_SYSTEM_MESSAGE, userMessage);
//
//					log.info("AI分析完成，准备保存结果");
//					AiCodeAnalysis analysis = new AiCodeAnalysis();
//					analysis.setProblemSubmitId(problemSubmitId);
//					analysis.setAnalysisResult(result);
//					analysis.setCreatedAt(LocalDateTime.now());
//
//					// 保存分析结果
//					aiCodeAnalysisService.saveAnalysis(analysis);
//					log.info("AI分析结果保存成功，ID: {}", problemSubmitId);
//
//				} catch (Exception e) {
//					log.error("AI分析处理失败，提交ID: {}", problemSubmitId, e);
//				}
//			});
//
//			return Result.success(problemSubmitId);
//
//		} catch (Exception e) {
//			log.error("提交失败", e);
//			return null;
//		}
//			// 异步处理（保持您原有的CompletableFuture方式）
//			CompletableFuture.runAsync(() -> {
//				try {
//					String result = aiManager.doSyncStableRequest(AI_ANALYSIS_SYSTEM_MESSAGE, userMessage);
//					saveAnalysisWithFallback(problemSubmitId, result);
//				} catch (Exception e) {
//					log.error("AI分析处理失败，提交ID: {}", problemSubmitId, e);
//				}
//			});
//
//			return Result.success(problemSubmitId);
//		} catch (Exception e) {
//			log.error("提交失败", e);
//			return null;
//		}

//	// 新增这个私有方法（放在Controller类内）
//	private void saveAnalysisWithFallback(Long problemSubmitId, String result) {
//		try {
//			// 首次尝试完整保存
//			AiCodeAnalysis analysis = AiCodeAnalysis.builder()
//					.problemSubmitId(problemSubmitId)
//					.analysisResult(result)
//					.createdAt(LocalDateTime.now())
//					.build();
//			aiCodeAnalysisService.saveAnalysis(analysis);
//		} catch (DataIntegrityViolationException e) {
//			// 如果内容过长，尝试截断后保存
//			log.warn("分析报告过长，尝试截断保存");
//			String truncatedResult = result.substring(0, Math.min(result.length(), 65535));
//			AiCodeAnalysis fallbackAnalysis = AiCodeAnalysis.builder()
//					.problemSubmitId(problemSubmitId)
//					.analysisResult(truncatedResult)
//					.createdAt(LocalDateTime.now())
//					.build();
//			aiCodeAnalysisService.saveAnalysis(fallbackAnalysis);
//		}
//	}
			// 先同步执行判题
			judgeService.doJudge(problemSubmitId);

			// 获取完整数据（包含判题结果）
			OjProblemSubmitVo submitVo = ojProblemSubmitService.getInfoById(problemSubmitId);

			CompletableFuture.runAsync(() -> {
				try {
					// 重新获取最新数据，确保判题完成
					OjProblemSubmitVo submit = ojProblemSubmitService.getInfoById(problemSubmitId);
					if (submit == null || submit.getJudgeInfo() == null) {
						log.warn("无法获取判题结果，跳过AI分析，提交ID: {}", problemSubmitId);
						return;
					}

					String userMessage = getGenerateUserMessage(submit);
					String analysisResult = aiManager.doSyncStableRequest(
							AI_ANALYSIS_SYSTEM_MESSAGE,
							userMessage
					);

					saveAnalysisWithRetry(problemSubmitId, analysisResult);
				} catch (Exception e) {
					log.error("AI分析失败，提交ID: {}", problemSubmitId, e);
				}
			});

			return Result.success(problemSubmitId);
		} catch (Exception e) {
			log.error("提交失败", e);
			return null;
		}
	}

	// 新增带重试的保存方法
	private void saveAnalysisWithRetry(Long submitId, String result) {
		int maxRetries = 3;
		for (int i = 0; i < maxRetries; i++) {
			try {
				AiCodeAnalysis analysis = AiCodeAnalysis.builder()
						.problemSubmitId(submitId)
						.analysisResult(result)
						.createdAt(LocalDateTime.now())
						.build();
				aiCodeAnalysisService.saveAnalysis(analysis);
				return;
			} catch (Exception e) {
				if (i == maxRetries - 1) throw e;
				try {
					Thread.sleep(1000 * (i + 1));
				} catch (InterruptedException ie) {
					Thread.currentThread().interrupt();
				}
			}
		}
	}

	@GetMapping("/analysis/{problemSubmitId}")
	@Operation(summary = "获取 AI 代码分析报告")
	public Result<String> getAnalysisReport(@PathVariable Long problemSubmitId) {
		Optional<AiCodeAnalysis> analysisOptional = aiCodeAnalysisService.getAnalysisByProblemSubmitId(problemSubmitId);
		if (analysisOptional.isPresent()) {
			return Result.success(analysisOptional.get().getAnalysisResult());
		}
		return Result.error("未找到分析报告");
	}

	@GetMapping("/getInfo/{id}")
	@Operation(summary = "根据主键获取题目提交信息")
	public Result<OjProblemSubmitVo> getInfo(@PathVariable Long id) {
		return Result.success(ojProblemSubmitService.getInfoById(id));
	}

	@PostMapping("/pageInfoByUserId/{id}")
	@Operation(summary = "根据用户id分页查询题目提交信息列表")
	public Result<Page<OjProblemSubmitVo>> pageInfoByUserId(@PathVariable Long id,
			@RequestBody OjProblemSubmitQueryRequest req, Paging paging) {
		return Result.success(ojProblemSubmitService.pageInfoByUserId(id, req, paging));
	}

}
